package esercitazione4.JUnitTest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

import org.junit.*;

import esercitazione4.BTree.BTree;
import esercitazione4.BTree.KeyDuplicateException;
import esercitazione4.BTree.NoKeyFoundException;
import esercitazione4.BTree.TreeEmptyException;
import static org.junit.Assert.*;

public class BTreeTest{
	private BTree<Integer,String> btree;
	// Dimensione minima di figli per nodo dell'albero
	final int DIM_TREE = 2;

	@Before
	public void setUp(){
		btree = new BTree<Integer, String>(DIM_TREE);
	}

	@Test
	public void testSizeWithInsertAndRemove() throws KeyDuplicateException, NoKeyFoundException, TreeEmptyException{
		int count = 0;

		assertEquals(count, btree.size());

		//Inserimenti
		btree.add(3, "tre");
		count++;
		assertEquals(count, btree.size());
		btree.add(5, "cinque");
		count++;
		assertEquals(count, btree.size());
		btree.add(2, "due");
		count++;
		assertEquals(count, btree.size());
		btree.add(1, "uno");
		count++;
		assertEquals(count, btree.size());
		btree.add(7, "sette");
		count++;
		assertEquals(count, btree.size());

		//Cancellazioni
		btree.delete(2);
		count--;
		assertEquals(count, btree.size());
		btree.delete(7);
		count--;
		assertEquals(count, btree.size());
		btree.delete(5);
		count--;
		assertEquals(count, btree.size());
		btree.delete(3);
		count--;
		assertEquals(count, btree.size());
		btree.delete(1);
		count--;
		assertEquals(count, btree.size());

		//Inserimenti e cancellazioni incrociate
		btree.add(3, "tre");
		count++;
		btree.add(5, "cinque");
		count++;
		btree.delete(3);
		count--;
		assertEquals(count, btree.size());
		btree.add(3, "tre");
		count++;
		btree.delete(3);
		count--;
		assertEquals(count, btree.size());

	}

	@Test(expected=NoKeyFoundException.class)
	public void testFind() throws KeyDuplicateException, NoKeyFoundException{
		btree.add(2, "due");
		btree.add(4, "quattro");
		btree.add(1, "uno");
		btree.add(0, "zero");
		btree.add(5, "cinque");
		btree.add(3, "tre");

		assertEquals("cinque", btree.get(5));
		assertEquals("zero", btree.get(0));
		assertEquals("tre", btree.get(3));
		assertEquals("due", btree.get(2));
		// Ricerca elemento non presente
		assertEquals("dieci", btree.get(10));
	}

	@Test(expected=KeyDuplicateException.class)
	public void testInsertRandom() throws KeyDuplicateException{
		// size dell'albero stimata
		int count = 0;
		// Massimo valore intero da inserire nell'albero (valore minimo = 0)
		final int MAX_RANGE_VALUE = 15;
		// Numero di nodi inseriti (in maniera sequenziale) nell'albero
		final int NUMBER_OF_INSERT = 15;

		//GLI ELEMENTI DELL'ARRAY DEVONO ESSERE DIVERSI FRA LORO, NO DOPPIONI
		ArrayList<Integer> array = new ArrayList<Integer>();

		int[] vector = new int[NUMBER_OF_INSERT];
		for(int k = 0; k < NUMBER_OF_INSERT; k++){
			Random rn = new Random();
			int range = MAX_RANGE_VALUE - 0 + 1;
			int randomNum =  rn.nextInt(range) + 0;

			if(array.contains(randomNum)){
				k--;
				continue;
			}
			else
				array.add(randomNum);

			vector[k] = randomNum;
		}

		for(int i : vector){
			btree.add(i, "Valore (" + i + ")");
			count++;
			assertEquals(count, btree.size());
		}

		//PROVA INSERIMENTO DOPPIONE (lancia eccezione)
		btree.add(vector[0], "Valore (" + vector[0] + ")");
		assertEquals(count, btree.size());
	}

	@Test
	public void testInsertAndDeleteInOrder() throws KeyDuplicateException, TreeEmptyException, NoKeyFoundException{
		// size dell'albero stimata
		int count = 0;
		// Massimo valore intero da inserire nell'albero (valore minimo = 0)
		final int MAX_RANGE_VALUE = 15;
		// Numero di nodi inseriti (in maniera sequenziale) nell'albero
		final int NUMBER_OF_INSERT = 15;

		// CONTIENE GLI ELEMENTI NELL'ALBERO ed EVITA I DOPPIONI
		ArrayList<Integer> vector = new ArrayList<Integer>(NUMBER_OF_INSERT);

		for(int k = 0; k < NUMBER_OF_INSERT; k++){
			Random rn = new Random();
			int range = MAX_RANGE_VALUE - 0 + 1;
			int randomNum =  rn.nextInt(range) + 0;

			if(vector.contains(randomNum)){
				k--;
				continue;
			}
			else
				vector.add(randomNum);
		}

		for(int i : vector){
			btree.add(i, "Valore (" + i + ")");
			count++;
			assertEquals(count, btree.size());
		}

		for(int i : vector){
			btree.delete(i);
			count--;
			assertEquals(count, btree.size());
		}
	}

	@Test
	public void testRemoveSmaller() throws KeyDuplicateException, NoKeyFoundException, TreeEmptyException{
		// size dell'albero stimata
		int count = 0;
		// Massimo valore intero da inserire nell'albero (valore minimo = 0)
		final int MAX_RANGE_VALUE = 15;
		// Numero di nodi inseriti (in maniera sequenziale) nell'albero
		final int NUMBER_OF_INSERT = 15;

		// CONTIENE GLI ELEMENTI NELL'ALBERO ed EVITA I DOPPIONI
		ArrayList<Integer> vector = new ArrayList<Integer>(NUMBER_OF_INSERT);

		for(int k = 0; k < NUMBER_OF_INSERT; k++){
			Random rn = new Random();
			int range = MAX_RANGE_VALUE - 0 + 1;
			int randomNum =  rn.nextInt(range) + 0;

			if(vector.contains(randomNum)){
				k--;
				continue;
			}
			else
				vector.add(randomNum);
		}

		for(int i : vector)
			btree.add(i, "Valore (" + i + ")");

		Collections.sort(vector);
		count = vector.size();

		for(int i : vector){
			btree.delete(i);
			count--;
			assertEquals(count, btree.size());
		}
	}

	@Test
	public void testRemoveBigger() throws KeyDuplicateException, NoKeyFoundException, TreeEmptyException{
		// size dell'albero stimata
		int count = 0;
		// Massimo valore intero da inserire nell'albero (valore minimo = 0)
		final int MAX_RANGE_VALUE = 15;
		// Numero di nodi inseriti (in maniera sequenziale) nell'albero
		final int NUMBER_OF_INSERT = 15;

		// CONTIENE GLI ELEMENTI NELL'ALBERO ed EVITA I DOPPIONI
		ArrayList<Integer> vector = new ArrayList<Integer>(NUMBER_OF_INSERT);

		for(int k = 0; k < NUMBER_OF_INSERT; k++){
			Random rn = new Random();
			int range = MAX_RANGE_VALUE - 0 + 1;
			int randomNum =  rn.nextInt(range) + 0;

			if(vector.contains(randomNum)){
				k--;
				continue;
			}
			else
				vector.add(randomNum);
		}

		for(int i : vector)
			btree.add(i, "Valore (" + i + ")");

		Collections.sort(vector);
		count = vector.size();

		while(vector.size() > 0){
			btree.delete(vector.remove(vector.size() - 1));
			count--;
			assertEquals(count, btree.size());
		}
	}
}
